package com.xdf.whiteaccount.service.impl;

import com.xdf.whiteaccount.dao.*;
import com.xdf.whiteaccount.dto.PlanDTO;
import com.xdf.whiteaccount.entity.*;
import com.xdf.whiteaccount.service.DyeFabricPlanService;
import com.xdf.whiteaccount.service.ProducePlanService;
import com.xdf.whiteaccount.service.base.BaseService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import com.xdf.whiteaccount.utils.BusinessException;
import com.xdf.whiteaccount.utils.Example;
import com.xdf.whiteaccount.utils.BeanUtils;
import com.xdf.whiteaccount.enums.OpeEnum;
import com.xdf.whiteaccount.enums.MoveBillFlag;
import org.springframework.util.Assert;

/**
 * @Description : 服务层实现类，由代码生成器自动生成
 * @Author : chanchaw
 * @Date : 2025-3-4 10:56:34
 */
@Slf4j
@Service
public class ProducePlanServiceImpl extends BaseService implements ProducePlanService {
    @Autowired
    private ProducePlanMapper dao;
    @Autowired
    private BaseService baseService;
    @Autowired
    private DyeFabricPlanService dyeFabricPlanService;
    @Autowired
    private GjrkbillCpMapper gjrkbillCpMapper;
    @Autowired
    private DyeFabricPlanMapper dyeFabricPlanMapper;
    @Autowired
    private GjrkbilldraftCpMapper gjrkbilldraftCpMapper;
    @Autowired
    private SysConfigIntMapper sysConfigIntMapper;
    @Autowired
    private DyeFabricPlanServiceImpl dyeFabricPlanServiceimpl;

    @Override
    @Transactional
    public ProducePlan insert(ProducePlan record) {
        record = fullFill(record);
        doBeforeInsert(record);
        dao.insert(record);
        doAfterInsert(record);
        return record;
    }

    @Override
    @Transactional
    public ProducePlan insertSelective(ProducePlan record) {
        if (record.getBillCode() == null) throw new RuntimeException("订单号不允许为空！！");
        record.setBillCode("BYJ" + LocalDate.now().getYear() + "-" + record.getBillCode());
        List<ProducePlan> list = dao.selectbyBillCode(record.getBillCode());
        if (list.size() > 0) throw new RuntimeException("订单号不允许重复！！");
        LocalDate now = LocalDate.now();
        ProducePlan producePlan = Optional.ofNullable(dao.selectByCreateTime()).orElse(new ProducePlan());
//        SysConfigInt sysConfigInt = sysConfigIntMapper.selectByPrimaryKey("初始订单号");
        Date createTime = producePlan.getCreateTime();
//        if(createTime == null){
//            record.setOrderCodeYear(sysConfigInt.getConfigValue());
//        }else{
            String s = producePlan.getCreateTime().toString();
            String[] strs = s.split(" ");
            if (strs[5].equals(String.valueOf(now.getYear()))) record.setOrderCodeYear(producePlan.getOrderCodeYear() + 1);
            else record.setOrderCodeYear(1);
//        }
        record.setBillCode(record.getBillCode());
        record.setCreateUser(getLoginUserName());
        dao.insertSelective(record);
        Integer[] arr = new Integer[]{record.getId()};
        dyeFabricPlanService.syncPlan(arr);
        return record;
    }

    /* 由于本方法无法返回所有对象的自增主键，后者调整为一个一个保存的方法
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int multiInsert(List<ProducePlan> list) {
        return dao.multiInsert(list);
    }
     */
    @Override
    @Transactional
    public List<ProducePlan> multiInsert(List<ProducePlan> list) {
        list.forEach(item -> insertSelective(item));
        return list;
    }

    @Override
    public int updateByPrimaryKey(ProducePlan record) {
        try {
            BeanUtils.fullFillRecord(record, OpeEnum.UPDATE);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return dao.updateByPrimaryKey(record);
    }

    @Override
    public int updateByPrimaryKeySelective(ProducePlan record) {
        try {
            BeanUtils.fullFillRecord(record, OpeEnum.UPDATE);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return dao.updateByPrimaryKeySelective(record);
    }

    @Override
    public int deleteByPrimaryKey(Integer id) {
        ProducePlan dbRecord = dao.selectByPrimaryKey(id);
        if( dbRecord == null ) return 0;
        dbRecord.setState(-1);
        return dao.updateByPrimaryKey(dbRecord);
    }

    @Override
    public ProducePlan selectByPrimaryKey(Integer id) throws Exception {
        ProducePlan producePlan = dao.selectByPrimaryKey(id);
        String billDate = producePlan.getBillDate().toString();
        String year = billDate.split(" ")[5];
        producePlan.setCode(producePlan.getBillCode());
        return producePlan;
    }

    // 根据主键作废
    @Override
    public int setVoid(Integer id){
        ProducePlan dbRecord = dao.selectByPrimaryKey(id);
        if( dbRecord == null ) return 0;
        dbRecord.setState(0);
        return dao.updateByPrimaryKey(dbRecord);
    }

    @Override
    public List<ProducePlan> selectAll(){
        return dao.selectAll();
    }

    @Override
    public ProducePlan save(ProducePlan record){
        if(record == null) throw new BusinessException("空对象不可保存！");
        Integer iid = Optional.ofNullable(record.getId()).orElse(0);
        if(iid==0) record = insertSelective(record);
        else updateByPrimaryKeySelective(record);
        return record;
    }

    // 没有使用 xml 中的 multiSave 方法是因为无法批量回写自增主键
    @Transactional
    @Override
    public List<ProducePlan> multiSave(List<ProducePlan> list){
        if(list == null || list.size()==0) return list;
        list.forEach(item -> item = save(item));
        return list;
    }

    /**=========================下面开始是固定模式代码=======================================*/
    // 新增前检测，不可新增则抛出异常
    private void check4Insert(ProducePlan record){
    }

    @Override
    public ProducePlan fullFill(ProducePlan record) {
        // TODO: 默认前端传递来的参数不需要填充完整，如果需要则使用自定义逻辑覆盖下面的代码
        try {
            // 根据“新增”或者“修改”填充创建人或者最后一次修改人
            // 要求表格中有字段：create_user,last_user
            BeanUtils.fullFillRecord(record,OpeEnum.NEW);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return record;
    }

    @Override
    public void doBeforeInsert(ProducePlan record) {
        // TODO: 在新增数据前需要做的逻辑写在这里，抛出异常则终止新增操作
        ProducePlanService.super.doBeforeInsert(record);
    }

    @Override
    public void doAfterInsert(ProducePlan record) {
        // TODO: 新增数据后需要做的逻辑写在这里，抛出异常则终止新增操作
        ProducePlanService.super.doAfterInsert(record);
    }

    @Override
    public List<ProducePlan> selectByExample(Example<ProducePlan> example){
        return dao.selectByExample(example);
    }

    @Override
    public ProducePlan moveBill(Integer id, String moveBillFlag){
        if(moveBillFlag.equalsIgnoreCase(MoveBillFlag.FIRST.getFlag())){
            ProducePlan first = dao.getFirst();
            if(first == null) throw new BusinessException("没有单据！");
            else return first;
        }

        if(moveBillFlag.equalsIgnoreCase(MoveBillFlag.LAST.getFlag())){
            ProducePlan last = dao.getLast();
            if(last == null) throw new BusinessException("没有单据！");
            else return last;
        }
        if(moveBillFlag.equalsIgnoreCase(MoveBillFlag.NEXT.getFlag())){
            ProducePlan next = dao.getNext(id);
            if(next == null) throw new BusinessException("没有下一单了！");
            else return next;
        }

        if(moveBillFlag.equalsIgnoreCase(MoveBillFlag.PREVIOUS.getFlag())){
            ProducePlan prev = dao.getPrev(id);
            if(prev == null) throw new BusinessException("没有上一单了！");
            else return prev;
        }

        return null;
        }

    //=================以上是自动生成的代码，自定义代码请写在下面==================

    @Override
    @Transactional
    public ProducePlan updateSelective(ProducePlan record) throws Exception {
        SysConfigInt sysConfigInt = sysConfigIntMapper.selectByPrimaryKey("生产计划上机数最大值");
        Integer configValue = sysConfigInt.getConfigValue();
        if (record.getMachineQty() > configValue) throw new RuntimeException("生成的卡片数超过最大值！！");
        ProducePlan producePlan = dao.selectByPrimaryKey(record.getId());//获取修改前的数据
        List<DyeFabricPlan> dyeFabricPlans = dyeFabricPlanService.selectOrderCode(producePlan.getBillCode());
        //修改上机数的情况
        int machineQty = record.getMachineQty() - dyeFabricPlans.size();
        if (machineQty < 0) {//减
            if (dyeFabricPlans.size() > 0) {
                for (int i = 0; i < dyeFabricPlans.size(); i++) {
                    DyeFabricPlan dyeFabricPlan = dyeFabricPlans.get(i);
                    List<GjrkbillCp> gjrkbillCpList = gjrkbillCpMapper.selectByBId(dyeFabricPlan.getId());
                    List<GjrkbilldraftCp> gjrkbilldraftCpList = gjrkbilldraftCpMapper.selectByBId(dyeFabricPlan.getId());
                    if (gjrkbillCpList.size() > 0 || gjrkbilldraftCpList.size() > 0) {
                        String code = dyeFabricPlan.getPlanCode().split("-")[1];
                        int codeNumber = Integer.parseInt(code);
                        if (codeNumber > record.getMachineQty()) throw new RuntimeException("检测到" + dyeFabricPlan.getPlanCode() + "已经打卷，修改数量超出允许范围！！");
                    }
                }
                for (DyeFabricPlan dyeFabricPlan : dyeFabricPlans) {
//                    List<GjrkbillCp> gjrkbillCpList = gjrkbillCpMapper.selectByBId(dyeFabricPlan.getId());
//                    List<GjrkbilldraftCp> gjrkbilldraftCpList = gjrkbilldraftCpMapper.selectByBId(dyeFabricPlan.getId());
//                    if (gjrkbillCpList.size() > 0 || gjrkbilldraftCpList.size() > 0) throw new RuntimeException("检测到" + dyeFabricPlan.getPlanCode() + "已经打卷，包括该机台号之前的卡片都不允许删除！！");
                    if (machineQty < 0) {
                        dyeFabricPlan.setState(0);
                        dyeFabricPlanMapper.updateByPrimaryKeySelective(dyeFabricPlan);
                        dyeFabricPlanService.deleteByPrimaryKey(dyeFabricPlan.getId());
                        machineQty = machineQty + 1;
                    }
                }
            }
        }
        if (machineQty > 0) {//加
            if (dyeFabricPlans.size() > 0) {
                int codeNumber = Integer.parseInt(dyeFabricPlans.get(0).getPlanCode().split("-")[1]);
                for (DyeFabricPlan dyeFabricPlan : dyeFabricPlans) {
                    int number = Integer.parseInt(dyeFabricPlan.getPlanCode().split("-")[1]);
                    if (codeNumber < number) codeNumber = number;
                }
                for (int i = 0; i < machineQty; i++) {
                    DyeFabricPlan dyeFabricPlan = new DyeFabricPlan();
                    org.springframework.beans.BeanUtils.copyProperties(dyeFabricPlans.get(0), dyeFabricPlan);
                    codeNumber++;
                    dyeFabricPlan.setPlanCode(dyeFabricPlans.get(0).getPlanCode().split("-")[0] + "-" + String.format("%02d", codeNumber));
                    dyeFabricPlan.setId(null);
                    dyeFabricPlanMapper.insertSelective(dyeFabricPlan);
                }
            } else if (dyeFabricPlans.size() == 0) {
                producePlan.setMachineQty(record.getMachineQty());
                for (int i = 1; i <= machineQty; i++) {
                    dyeFabricPlanServiceimpl.addPlan(producePlan, i);
                }
            }
        }
        List<DyeFabricPlan> dFPlans = dyeFabricPlanService.selectOrderCode(producePlan.getBillCode());
        record.setMachineQty(dFPlans.size());
        dao.updateByPrimaryKeySelective(record);

        //将订单的字段同步至卡片
        if (dyeFabricPlans.size() != 0) getToDyePlan(record, dyeFabricPlans);

        return record;
    }

    //将订单的字段同步至卡片
    private void getToDyePlan(ProducePlan record, List<DyeFabricPlan> dyeFabricPlans) {
        for (DyeFabricPlan plan : dyeFabricPlans) {
            plan.setContactCompanyId(record.getClient());//往来单位
            plan.setProductName(record.getProductName());//品名
            plan.setMaterialSpecification(record.getFabricSpecification());//克重
            plan.setMaterialLotNo(record.getProductSpecification());//定长定重
            plan.setGreyfabricWeight(record.getFabricSpecification());//白坯克重
            plan.setGreyfabricWidth(record.getFabricWidth());//白坯门幅
            plan.setPlanKilo(record.getKilo());//计划重
            plan.setSubmitDate(record.getShippingDate());//出货日期
            plan.setShape(record.getYarnTotal());//总经（原中丝规格）
            plan.setRemarkLabel(record.getLongitude());//经纱（原外键,中丝供应商）
            plan.setRemarkProduce(record.getLatitude());//纬纱（原中丝头份）
            plan.setRemarkDelivery(record.getLatilong());//经纬密度（原底丝供应商）
            plan.setTube(record.getKouWidth());//筘幅(底丝头份)
            plan.setColor(record.getColor());//颜色
            plan.setClientAlias(record.getAlias());//客户别名
            dyeFabricPlanMapper.updateByPrimaryKey(plan);
        }
    }

    @Override
    public void auditAll() {
        dao.auditAll();
    }

    @Override
    public void setFinishedMark(Integer id) {
        ProducePlan producePlan = dao.selectByPrimaryKey(id);
//        if (producePlan.getState() != 2) throw new RuntimeException("未经审核，不允许完工！");
        producePlan.setState(4);
        dao.updateByPrimaryKeySelective(producePlan);
    }

    @Override
    public void setNoFinishedState(Integer id) {
        ProducePlan producePlan = dao.selectByPrimaryKey(id);
        if (producePlan == null && Optional.ofNullable(producePlan.getState()).orElse(1) == 0) throw new RuntimeException("单据不存在或已作废！");
        producePlan.setState(1);
        dao.updateByPrimaryKeySelective(producePlan);
    }

    @Override
    public ProducePlan selectMax() {
        return dao.selectMax();
    }

    @Override
    public String maxOrderCode() {
        ProducePlan producePlan = selectMax();
        SysConfigInt sysConfigInt = sysConfigIntMapper.selectByPrimaryKey("初始订单号");
        Integer orderCodeYear;
        if (producePlan == null)  orderCodeYear = sysConfigInt.getConfigValue() - 1;
        else orderCodeYear = producePlan.getOrderCodeYear();
        int year = LocalDate.now().getYear();
        return "BYJ" + year + "-" + String.format("%03d", orderCodeYear + 1);
    }

    @Override
    public List<Map<String, Object>> selectByKCMX(Integer id) {
        return dao.selectByKCMX(id);
    }
}